package com.syh.jn.scm.infrastructure.repository.impl.supplier.stock;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtStringUtils;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.infrastructure.repository.AggregateRepoHibernateImplTmpl;
import com.syh.jn.scm.domain.supplier.entity.stock.StockOtherOutBill;
import com.syh.jn.scm.domain.supplier.entity.stock.StockOtherOutBillItem;
import com.syh.jn.scm.domain.supplier.repository.stock.StockOtherOutBillRepository;
import com.syh.jn.scm.dto.supplier.stock.StockOtherOutBillItemVo;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsBrandModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsCategoryModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsModel;
import com.syh.jn.scm.infrastructure.repository.model.stock.stockOtherOutBill.StockOtherOutBillItemModel;
import com.syh.jn.scm.infrastructure.repository.model.stock.stockOtherOutBill.StockOtherOutBillModel;
import lombok.extern.java.Log;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 其它出入库
 */
@Log
@Repository
public class StockOtherOutBillRepositoryImpl implements StockOtherOutBillRepository {

  private HibernateTemplate hibernateTemplate;

  private AggregateRepoHibernateImplTmpl<StockOtherOutBill, StockOtherOutBillModel, Long> billTmpl;
  private AggregateRepoHibernateImplTmpl<StockOtherOutBillItem, StockOtherOutBillItemModel, Long> itemTmpl;

  @Autowired
  public StockOtherOutBillRepositoryImpl(HibernateTemplate hibernateTemplate) {
    this.hibernateTemplate = hibernateTemplate;
    this.billTmpl = new AggregateRepoHibernateImplTmpl.Builder()
            .hibernateTemplate(hibernateTemplate)
            .idClass(Long.class)
            .entityClass(StockOtherOutBill.class)
            .modelClass(StockOtherOutBillModel.class)
            .build();

    this.itemTmpl = new AggregateRepoHibernateImplTmpl.Builder()
            .hibernateTemplate(hibernateTemplate)
            .idClass(Long.class)
            .entityClass(StockOtherOutBillItem.class)
            .modelClass(StockOtherOutBillItemModel.class)
            .build();

  }

  /**
   * 重写add方法
   *
   * @param stockOtherOutBill
   * @return
   */
  @Override
  public Long add(StockOtherOutBill stockOtherOutBill) {
    //保存其他出库入单
    Long id = this.billTmpl.add(stockOtherOutBill).getId();
    //保存其他出入库单项
    this.saveItems(id, stockOtherOutBill.getItems());
    return id;
  }

  /**
   * 重写update方法
   *
   * @param stockOtherOutBill
   */
  @Override
  public void update(StockOtherOutBill stockOtherOutBill) {
    this.update(stockOtherOutBill, true);
  }

  /**
   * 重载update方法,选择是否更新订单项
   *
   * @param stockOtherOutBill
   * @param isUpdateItem
   */
  @Override
  public void update(StockOtherOutBill stockOtherOutBill, boolean isUpdateItem) {
    if (isUpdateItem) {
      this.delItemsById(stockOtherOutBill.getId());
      this.saveItems(stockOtherOutBill.getId(), stockOtherOutBill.getItems());
    }
    this.billTmpl.update(stockOtherOutBill);

  }

  /**
   * 重写getById方法,默认包含item
   *
   * @param aLong
   * @return
   */
  @Override
  public StockOtherOutBill getById(Long aLong) {
    StockOtherOutBill stockOtherOutBill = this.billTmpl.getById(aLong);
    List<StockOtherOutBillItem> stockOtherOutBillItems = this.getItemsById(aLong);
    stockOtherOutBill.setItems(stockOtherOutBillItems);
    return stockOtherOutBill;
  }

  @Override
  public StockOtherOutBill getOne(Wrapper wrapper) {
    return billTmpl.getOne(wrapper);
  }

  @Override
  public List<StockOtherOutBill> getList(Wrapper wrapper) {
    return billTmpl.getList(wrapper);
  }

  @Override
  public List<StockOtherOutBill> findListPage(Wrapper wrapper, Integer startRow, Integer count) {
    return billTmpl.findListPage(wrapper, startRow, count);
  }

  @Override
  public int getCount(Wrapper wrapper) {
    return billTmpl.getCount(wrapper);
  }

  @Override
  public boolean contains(Long aLong) {
    return billTmpl.contains(aLong);
  }

  @Override
  public StockOtherOutBill getById(Long id, boolean haveItems) {
    return haveItems ? this.getById(id) : this.billTmpl.getById(id);
  }

  @Override
  public StockOtherOutBillItem getItemByItemId(Long id) {
    return this.itemTmpl.getById(id);
  }

  /**
   * 重写removeById方法
   *
   * @param aLong
   */
  @Override
  public void removeById(Long aLong) {
    this.billTmpl.removeById(aLong);
    this.delItemsById(aLong);
  }

  /**
   * 重写remove方法
   *
   * @param stockOtherOutBill
   */
  @Override
  public void remove(StockOtherOutBill stockOtherOutBill) {
    this.billTmpl.removeById(stockOtherOutBill.getId());
    this.delItemsById(stockOtherOutBill.getId());
  }

  @Override
  public List<StockOtherOutBillItem> findStockOtherOutBillItemListPage(Wrapper wrapper, Integer startRow, Integer count) {
    log.warning("该接口暂不实现");
    return Collections.EMPTY_LIST;
  }

  @Override
  public int findStockOtherOutBillItemListPageCount(Wrapper wrapper) {
    return this.itemTmpl.getCount(wrapper);
  }

  /**
   * 根据服务商id删除采购单
   * @param businessEntityId
   */
  @Override
  public void deleteByBusinessEntityId(Long businessEntityId) {
    String itemHql = "delete from StockOtherOutBillItemModel where businessEntityId = :businessEntityId";
    Query itemQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(itemHql);
    itemQuery.setParameter("businessEntityId",businessEntityId);
    itemQuery.executeUpdate();
    String orderHql = "delete from StockOtherOutBillModel where businessEntityId = :businessEntityId";
    Query orderQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(orderHql);
    orderQuery.setParameter("businessEntityId",businessEntityId);
    orderQuery.executeUpdate();
  }

  @Override
  public List<StockOtherOutBillItemVo> findStockOtherOutBillItemVoByBillId(Long stockOtherOutBillId) {
    log.warning("该接口暂不实现");
    return Collections.EMPTY_LIST;
  }

  @Override
  public List<StockOtherOutBillItemVo> findStockOtherOutBillItemVoListPage(Wrapper wrapper, Integer startRow, Integer count) {
    log.warning("该接口暂不实现");
    return Collections.EMPTY_LIST;
  }

  @Override
  public int findStockOtherOutBillItemVoCount(Wrapper wrapper) {
    return this.itemTmpl.getCount(wrapper);
  }

  /**
   * 添加出入库单项
   *
   * @param id
   * @param stockOtherOutBillItems
   */
  private void saveItems(Long id, List<StockOtherOutBillItem> stockOtherOutBillItems) {
    stockOtherOutBillItems.forEach(stockOtherOutBillItem -> {
      StockOtherOutBillModel stockOtherOutBillModel = this.hibernateTemplate.get(StockOtherOutBillModel.class, id);
      stockOtherOutBillItem.setStockOtherOutBillId(id);
      stockOtherOutBillItem.setBusinessEntityId(stockOtherOutBillModel.getBusinessEntityId());
      GoodsModel goodsModel = this.hibernateTemplate.get(GoodsModel.class, stockOtherOutBillItem.getGoodsId());
      GoodsBrandModel goodsBrandModel = new GoodsBrandModel();
      if (goodsModel.getGoodsBrandId() != null) {
        goodsBrandModel = this.hibernateTemplate.get(GoodsBrandModel.class, goodsModel.getGoodsBrandId());
      }
      GoodsCategoryModel goodsCategoryModel = new GoodsCategoryModel();
      if (goodsModel.getCategoryId() != null) {
        goodsCategoryModel = this.hibernateTemplate.get(GoodsCategoryModel.class, goodsModel.getCategoryId());
      }
      StockOtherOutBillItemModel stockOtherOutBillItemModel = new StockOtherOutBillItemModel();
      ExtBeanUtils.copyProperties(stockOtherOutBillItem, stockOtherOutBillItemModel);
      //在仓储层冗余是为了安全和数据的准确
      stockOtherOutBillItemModel.setGoodsName(goodsModel.getName());
      stockOtherOutBillItemModel.setSpecName(goodsModel.getSpecName());
      stockOtherOutBillItemModel.setGoodsCode(goodsModel.getCode());
      stockOtherOutBillItemModel.setIsDefaultGoods(goodsModel.getIsDefaultGoods());
      stockOtherOutBillItemModel.setConversionRate(goodsModel.getConversionRate());
      stockOtherOutBillItemModel.setCodeBar(goodsModel.getCodeBar());
      stockOtherOutBillItemModel.setUnits(goodsModel.getUnits());
      stockOtherOutBillItemModel.setCategoryId(goodsModel.getCategoryId());
      stockOtherOutBillItemModel.setCategoryName(goodsCategoryModel.getName());
      stockOtherOutBillItemModel.setCategoryCatalogCode(goodsCategoryModel.getCatalogCode());
      stockOtherOutBillItemModel.setGoodsBrandId(ExtStringUtils.isBlank(goodsModel.getGoodsBrandId()) ? null : goodsModel.getGoodsBrandId());
      stockOtherOutBillItemModel.setGoodsBrandName(ExtStringUtils.isBlank(goodsBrandModel.getName()) ? null : goodsBrandModel.getName());
      this.hibernateTemplate.save(stockOtherOutBillItemModel);

    });
  }

  /**
   * 删除出入库单项
   *
   * @param stockOtherOutId
   */
  private void delItemsById(Long stockOtherOutId) {

    String hql = "delete StockOtherOutBillItemModel model WHERE model.stockOtherOutBillId = :stockOtherOutBillId";
    Query query = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(hql);
    query.setLong("stockOtherOutBillId", stockOtherOutId);
    query.executeUpdate();
  }

  /**
   * 根据出入库记录id获取出入库记录项
   *
   * @param stockOtherOutId
   * @return
   */
  public List<StockOtherOutBillItemModel> getItemsModleById(Long stockOtherOutBillId) {
    //获取库存项
    String hql = "FROM StockOtherOutBillItemModel model WHERE model.stockOtherOutBillId = ?";
    List<StockOtherOutBillItemModel> stockOtherOutBillItemModels = (List<StockOtherOutBillItemModel>) this.hibernateTemplate.find(hql, stockOtherOutBillId);

    return stockOtherOutBillItemModels;
  }

  /**
   * 根据出入库记录id获取出入库记录项
   *
   * @param stockOtherOutBillId
   * @return
   */
  public List<StockOtherOutBillItem> getItemsById(Long stockOtherOutBillId) {
    //获取库存项
    List<StockOtherOutBillItemModel> stockOtherOutBillItemModels = this.getItemsModleById(stockOtherOutBillId);
    List<StockOtherOutBillItem> stockOtherOutBillItems = new ArrayList<>();
    stockOtherOutBillItemModels.forEach(stockOtherOutBillItemModel -> {
      StockOtherOutBillItem stockOtherOutBillItem = new StockOtherOutBillItem();
      ExtBeanUtils.copyProperties(stockOtherOutBillItemModel, stockOtherOutBillItem);
      stockOtherOutBillItems.add(stockOtherOutBillItem);
    });
    return stockOtherOutBillItems;
  }
}
